home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
tex
/
dvi
/
dvist3_3.arc
/
SERVER.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-05-03
|
11KB
|
609 lines
/*
Remote file server written by Avygdor Moise and Tyler Ivanco
Copyright by Avygdor moise and Tyler Ivanco Mar 1987, all rights
reserved.
We release this program into the public domain with the following
restrictions:
This program may be freely distributed free of charge in source
and in binary, provided that the copyright notice is preserved
in the body of the program and any printed documentation that
is included with the client/server programs.
This program MAY not be sold or become a part of a commercial package
without prior WRITTEN authorization from the authors.
You may add new features and extensions to this software provided
that you notify the authors, so we can update our own original to
ensure that only one version of this program is circulating among the
various users.
The authors may be reached at
York University
Center for Research in Experimental Space Science
North York
Ontario, Canada.
and via EMAIL
BITNET: FS300013@SOL
FS300022@SOL
USENET: mnetor!yetti!gen1!tyler
mnetor!yetti!yugas!avy
*/
#ifdef VMS
# include stdio
#else
# include <stdio.h>
# ifdef OSK
# include <sgstat.h>
# define _IOEOF _EOF
# endif
#endif
#ifndef STDIN
# define STDIN 1 /* So that server can be started by a shell script */
#endif
extern FILE *fopen();
extern long ftell();
extern int errno;
#define TRUE (1)
#define FALSE (0)
#define EOR (0x0D)
#define EOL (0x0A)
#define XON (0x11)
#define XOFF (0x13)
#ifdef DEBUG1
# define DEBUG
#endif
#ifdef DEBUG
# define ACK 'A'
# define NAK 'N'
#else
# define ACK (0x06)
# define NAK (0x15)
#endif
#define E_OK '0'
#define E_CHECK '1'
#define E_INVREQ '2'
#define E_READ '3'
#define E_WRITE '4'
#define E_OPEN '5'
#define E_EOF '6'
#define E_NOFILE '7'
#define E_SEEK '8'
#define PACKET_SIZE (256)
#define BUF_SIZE (2*PACKET_SIZE + 10)
#define MAX_FILES (16)
#define loop for(;;)
char inp_buf[BUF_SIZE],out_buf[BUF_SIZE],tmp_buf[BUF_SIZE];
FILE *file[MAX_FILES];
int nfiles,packet_len;
main()
{
init();
loop
{
if( get_packet() ) switch( inp_buf[0] ) /* got a valid packet */
{
case '?': /* inquire */
pos_ack();
break;
case ACK: /* sync */
break;
case 'i': /* initalize - close all files */
close_all_req();
break;
case 'e': /* end - terminate server */
exit_req();
break;
case 'o': /* open file */
open_req();
break;
case 'c': /* close file */
close_req();
break;
case 'r': /* read data */
read_req();
break;
case 'w': /* write data */
write_req();
break;
case 's': /* seek to byte */
seek_req();
break;
case 't': /* tell current position */
tell_req();
break;
default:
neg_ack(E_INVREQ);
}
else
{
if( strncmp(inp_buf,"exit",4) == 0 ) exit_req();
neg_ack(E_CHECK);
}
}
}
neg_ack(err)
int err;
{
char c;
c = NAK;
write(1,&c,1);
c = err;
write(1,&c,1);
#ifdef DEBUG1
fprintf(stderr,"neg_ack called err = %d.\n",err);
#endif
}
pos_ack()
{
char c;
c = ACK;
write(1,&c,1);
#ifdef DEBUG1
fprintf(stderr,"pos_ack called.\n");
#endif
}
int get_packet()
{
int i,j,ret;
char c;
#ifdef DEBUG1
fprintf(stderr,"Enter get_packet:\n");fflush(stderr);
#endif
ret = FALSE;
for(i=0; i<BUF_SIZE; i++)
{
read(STDIN,&c,1);
#ifdef DEBUG1
fprintf(stderr,"[%02x]",(int)c & 0xff); fflush(stderr);
#endif
if( c == ACK ) /* unconditional quit */
{
inp_buf[0] = ACK;
ret = TRUE;
break;
}
if( (c == EOR) || (c == EOL) ) /* at end of packet */
{
if( i >= 2 ) /* at least 3 bytes <cmd><chk><EOR> */
{
packet_len = --i; /* drop the EOR byte */
for(j=c=0; j<i; j++) /* compute checksum */
{
c += inp_buf[j];
}
#ifdef DEBUG
if(inp_buf[i] != '.')
#else
if( c != inp_buf[i] )
#endif
{
#ifdef DEBUG1
fprintf(stderr,
"\nget_packet: bad checksum - c=[%02x], inp=[%02x]\n",
c & 0xff, inp_buf[i] & 0xff);
#endif
c = EOR;
break;
}
inp_buf[i] = '\0'; /* make it a string */
ret = TRUE; /* good record */
break;
}
else
break;
}
if( c == '-' ) /* an escape character */
{
read(STDIN,&c,1);
#ifdef DEBUG1
fprintf(stderr,"[%02x]",(int)c & 0xff); fflush(stderr);
#endif
if( c == ACK ) /* unconditional quit */
{
inp_buf[0] = ACK;
ret = TRUE;
break;
}
c -= '@';
}
inp_buf[i] = c;
}
if( ret == FALSE ) /* no EOR ... i.e. buffer overflow */
{
while( (c != EOR) && (c != EOL) && (c != ACK) )
{
#ifdef DEBUG1
fprintf(stderr,"get_packet: sync loop\n");
#endif
read(STDIN, &c, 1);
#ifdef DEBUG1
fprintf(stderr,"[%02x]",(int)c & 0xff);fflush(stderr);
#endif
}
if( c == ACK )
{
inp_buf[0] = ACK;
ret = TRUE;
}
else
ret = FALSE;
}
#ifdef DEBUG1
fprintf(stderr,"\nget_packet: ret = %d\n",ret);
#endif
return(ret);
}
reply(buffer,count)
char *buffer;
int count;
{
int i,j;
char sum,c;
#ifdef DEBUG1
fprintf(stderr,"Enter reply: buffer length = %d\n",count);
#endif
out_buf[0] = sum = 'd';
for(i=0,j=1; i<count; i++)
{
c = buffer[i];
sum += c; /* checksum on true data not trasformed one */
switch( c )
{
case ACK:
case NAK:
case EOR:
case EOL:
case XON:
case XOFF:
case '-':
out_buf[j++] = '-';
out_buf[j++] = buffer[i] + '@';
break;
default:
out_buf[j++]= buffer[i];
}
}
#ifdef DEBUG
out_buf[j++] = '.';
#else
if(( (sum & 0xE0) == 0 ) || (sum == '-'))
{
out_buf[j++] = '-';
sum += '@';
}
out_buf[j++] = sum;
#endif
out_buf[j++] = EOL;
loop
{
write(1,out_buf,j); /* send the data */
#ifdef DEBUG1
fprintf(stderr,"reply: out_buf length = %d\n",j);
for(i=0; i<j; i++) fprintf(stderr,"[%02x]", (int)out_buf[i] & 0xff);
fprintf(stderr,"\n");
#endif
read(STDIN,&sum,1); /* await ACK */
#ifdef DEBUG1
fprintf(stderr,"reply: expecting ACK, got [%02x]\n",(int)sum & 0xff);
#endif
switch(sum)
{
case NAK: /* not received try again */
break;
case ACK: /* received O.K. so quit */
return;
}
}
}
init()
{
int i;
sysinit();
for(i=0; i<MAX_FILES; i++)
{
file[i] = (FILE *)0;
}
nfiles = 0;
#ifdef DEBUG1
fprintf(stderr,"init called.\n");
#endif
}
close_all_req()
{
int i;
for(i=0; i<MAX_FILES; i++)
{
if(file[i])
{
fclose(file[i]);
file[i] = (FILE *)0;
}
}
nfiles = 0;
pos_ack();
#ifdef DEBUG1
fprintf(stderr,"close_all_req called.\n");
#endif
}
exit_req()
{
close_all_req();
systerm();
#ifdef DEBUG1
fprintf(stderr,"exit_req called.\n");
#endif
exit(0);
}
open_req() /* <o><mode><filename> */
{
int i,rewind;
char *mode;
FILE *fp;
#ifdef DEBUG1
fprintf(stderr,"open_req called '%s'.\n",inp_buf);
#endif
rewind = 0;
switch(inp_buf[1])
{
case 'r':
mode = "r";
break;
case 'w':
mode = "w";
break;
case 'u':
mode = "r+";
break;
case 'c':
mode = "w+";
break;
case 'a':
mode = "r+";
rewind = 2;
break;
default:
neg_ack(E_INVREQ);
return;
}
if( (nfiles > MAX_FILES) || ((fp=fopen(&inp_buf[2],mode)) == (FILE *)0) )
{
neg_ack(E_OPEN);
return;
}
fseek(fp, 0L, rewind);
for(i=0; i<MAX_FILES; i++)
{
if( file[i] == (FILE *)0 ) break;
}
file[i] = fp;
nfiles++;
tmp_buf[0] = i + '@';
pos_ack();
reply(tmp_buf,1);
}
close_req() /* <c><filedes> */
{
int i;
#ifdef DEBUG1
fprintf(stderr,"close_req called '%c'.\n",inp_buf[1] & 0xff);
#endif
i = inp_buf[1] - '@';
if( (i>=0) && (i<MAX_FILES) && file[i] )
{
fclose(file[i]);
nfiles--;
file[i] = (FILE *)0;
pos_ack();
}
else
neg_ack(E_NOFILE);
}
seek_req()
{
int i,rewind;
long pos;
#ifdef DEBUG1
fprintf(stderr,"seek_req called '%c'.\n",inp_buf[1] & 0xff);
#endif
i = inp_buf[1] - '@';
if( (i>=0) && (i<MAX_FILES) && file[i] )
{
pos =